<?php
namespace App\Api\Application;

use App\Common as com;
use App\Api as nameApi;
use App\Common\Server\Api as nameServerApi;
use App\Api\Application\Base as nameBase;
use App\Common\Server\Api\Gateway as nameGateway;

/**
 * Class ApiBase
 * @property-read array $apiParam api参数
 */
abstract class Base extends nameApi\Base {

	/**
	 * [token配置]是否为需要token(不签名验证、权限及网关的相关检测)
	 * @var bool [false]不需要 [true][默认]需要
	 */
	public bool $tokenConfig_IsNeedToken = true;

	/**
	 * [token配置]是否为检查权限
	 * @var bool [false]不需要 [true][默认]需要
	 */
	public bool $tokenConfig_IsCheckAuth = true;

	/**
	 * 自动验证规则
	 * @var array
	 */
	protected array $verifyRules = [];

	/**
	 * 自动验证失败说明信息
	 * @var array
	 */
	protected array $verifyErrorMessage = [];

	/**
	 * @var array
	 */
	private array $param;

	/**
	 * api请求对象(实例化时需初始化)(不可直接使用，调用方法：$this->apiResponse())
	 * @var nameGateway\ApiRequest|null
	 */
	private nameGateway\ApiRequest|null $_apiRequest = null;

	public function __construct( nameGateway\ApiRequest $apiRequest ) {
		$this->_apiRequest = $apiRequest;
		//
		parent::__construct();
	}

	/**
	 * 验证
	 * @return string|bool [{string}]错误信息(仅返回第一条错误) [true]验证通过
	 */
	private function verifyApiParam(  ):string|bool {
		if( empty( $this->verifyRules ) ) return true;
		//
		$validatorRes = $this->apiRequest()->apiData()->apiParam()->verifyData( $this->verifyRules, $this->verifyErrorMessage );
		if( ! $validatorRes->fails() ){
			return true;
		}
		return $validatorRes->errors()->first( null, ":key错误，错误信息：:message" );
	}

	/**
	 * [接口]执行api
	 * @param nameGateway\ApiRequest $apiRequest
	 * @param nameServerApi\Lib\ApplicationParamDto $apiParamDto
	 * @return nameGateway\ApiResponse|array
	 * @throws
	 */
	public function excApi( nameGateway\ApiRequest $apiRequest, nameServerApi\Lib\ApplicationParamDto $apiParamDto ):nameGateway\ApiResponse|array {
		//
		/*
		if( $apiParam === null ){
			$apiParam = $this->apiRequest()->apiData()->apiParam()->get();
		}else{
			$this->apiRequest()->apiData()->apiParam()->set( $apiParam );
		}
		*/
		// 验证
		$verifyRes = $this->verifyApiParam();
		if( $verifyRes !== true ){
			return $this->apiRequest()->apiResponse()->ofError( com\Lib\Err\Code::$apiSysParamError, $verifyRes );
		}
		//
		$this->checkAuth( $apiRequest, $apiParamDto );
		//
		return $this->_excApi( $apiRequest, $apiParamDto );
	}

	/**
	 * 执行api
	 * @param nameGateway\ApiRequest $apiRequest
	 * @param nameServerApi\Lib\ApplicationParamDto $apiParamDto
	 * @return com\Server\Api\Gateway\ApiResponse|array
	 * @throws
	 */
	abstract protected function _excApi( nameGateway\ApiRequest $apiRequest, nameServerApi\Lib\ApplicationParamDto $apiParamDto ):nameGateway\ApiResponse|array;

	/**
	 * 设置api参数
	 * @param array $apiParam
	 * @return $this
	 */
	public function setApiParam( array $apiParam ):self {
		$this->apiParam = $apiParam;
		return $this;
	}

	/**
	 * 获取api参数
	 * @return array
	 */
	public function getApiParam(  ):array {
		if( ! isset( $this->apiParam ) ){
			return $this->apiRequest()->apiData()->apiParam()->get();
		}else{
			return $this->apiParam;
		}
	}

	/**
	 * 设置执行参数
	 * @param array $param
	 * @return static
	 */
	public function setParam( array $param ):static {
		$this->param = $param;
		//
		return $this;
	}

	/**
	 * 获取执行参数
	 * @return array
	 */
	public function getParam(  ):array {
		return $this->param;
	}

	/**
	 * @param nameGateway\ApiRequest $apiRequest
	 * @param nameServerApi\Lib\ApplicationParamDto $apiParamDto
	 * @return void
	 * @throws
	 */
	private function checkAuth( nameGateway\ApiRequest $apiRequest, nameServerApi\Lib\ApplicationParamDto $apiParamDto ):void {
		if( $this->apiRequest()->accessToken()->isValid() ){
			$skipCheckAuth = $this->apiRequest()->accessToken()->session()->getOfPath( 'debug.skipCheckAuth', 0 );
			if( $skipCheckAuth ){
				return;
			}
		}
		/*
		if( $skipCheckAuth ){
			$apiDebugInfoConfig = Config::get( 'api.debugInfo' );
			if( $apiDebugInfoConfig['isDebugMode'] == true){
				if( $this->apiRequest()->token()->isValid() && $this->apiRequest()->token()->session()->getOfPath( 'isDebugUser' ) == 1 ){
					return;
				}
			}
		}
		*/
		// 检查权限
		if( method_exists( $this, '_checkAuth' ) ){
			$checkRes = $this->_checkAuth( $apiRequest, $apiParamDto );
			if( $checkRes !== true ){
				if( is_string( $checkRes ) ){
					$tisStr = $checkRes;
				}
				throw com\Lib\Err\Exception::makeOfNew( $tisStr ?? '', com\Lib\Err\Code::$sysNotAuth );
			}
		}
	}

	/**
	 * api请求对象
	 * @return nameGateway\ApiRequest
	 */
	public function apiRequest(  ):nameGateway\ApiRequest {
		return $this->_apiRequest;
	}

	/**
	 * api响应对象
	 * @return nameGateway\ApiResponse
	 */
	public function apiResponse(  ):nameGateway\ApiResponse {
		return $this->apiRequest()->apiResponse();
	}


	/**
	 * 格式化为api数组格式
	 * @param array|null $apiResData
	 * @return array|null
	 */
	protected function keyNameToParseNameToApiArray( array|null $apiResData ):array|null {
		if( $apiResData === null ){
			return null;
		}
		return com\Lib\Fun\Array_::keyNameToParseNames( $apiResData, 1, false );
	}

}
